﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace Rabbit客户端
{
    public partial class Form1 : Form
    {
        ConnectionFactory factory;

        public Form1()
        {
            InitializeComponent();
            factory = new ConnectionFactory { HostName = "localhost", Port = 5672 };
        }

        /// <summary>
        /// 初始化链接消息队列
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 发送消息给简单队列
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    QueueDeclareOk queue = channel.QueueDeclare(queue: "testqueue", durable: true, exclusive: false, autoDelete: false, arguments: null);
                    var body = Encoding.UTF8.GetBytes(textBox1.Text);
                    channel.BasicPublish(exchange: string.Empty, routingKey: "testqueue", basicProperties: null, body: body);
                    MessageBox.Show($"消息发送完成:{textBox1.Text},{queue.ConsumerCount}");
                }
            };
        }
        /// <summary>
        /// 交换机
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                var qName = "test_fanout";
                var qName1 = "test_fanout_queue1";
                var qName2 = "test_fanout_queue2";
                var exchangeName = "test_fanout";
                var exchangeType = "fanout";//topic、fanout
                var routingKey = "*";
                using (var connection = factory.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        // 设置交换器的类型
                        channel.ExchangeDeclare(exchangeName, exchangeType, durable: true);

                        // 声明一个队列，设置队列是否持久化，排他性，与自动删除
                        channel.QueueDeclare(qName, true, false, false, null);
                        channel.QueueDeclare(qName1, true, false, false, null);
                        channel.QueueDeclare(qName2, true, false, false, null);

                        // 绑定消息队列，交换器，routingkey
                        channel.QueueBind(qName, exchangeName, routingKey);
                        channel.QueueBind(qName1, exchangeName, routingKey);
                        channel.QueueBind(qName2, exchangeName, routingKey);

                        var properties = channel.CreateBasicProperties();

                        // 队列持久化
                        properties.Persistent = true;
                        var body = Encoding.UTF8.GetBytes(textBox1.Text);

                        // 发送信息
                        channel.BasicPublish(exchangeName, routingKey, properties, body);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 交换机
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                var qName1 = "test_direct_queue1";
                var qName2 = "test_direct_queue2";
                var exchangeName = "test_direct";
                var exchangeType = "direct"; //direct
                var routingKey = "*";
                using (var connection = factory.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        // 设置交换器的类型
                        channel.ExchangeDeclare(exchangeName, exchangeType, durable: true);
                        // 声明一个队列，设置队列是否持久化，排他性，与自动删除
                        channel.QueueDeclare(qName1, true, false, false, null);
                        channel.QueueDeclare(qName2, true, false, false, null);
                        // 绑定消息队列，交换器，routingkey
                        channel.QueueBind(qName1, exchangeName, routingKey);
                        channel.QueueBind(qName2, exchangeName, routingKey);
                        var properties = channel.CreateBasicProperties();
                        // 队列持久化
                        properties.Persistent = true;
                        var body = Encoding.UTF8.GetBytes(textBox1.Text);
                        // 发送信息
                        channel.BasicPublish(exchangeName, routingKey, properties, body);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                var qName1 = "test_topic_queue1";
                var qName2 = "test_topic_queue2";
                var qName3 = "test_topic_queue3";
                var exchangeName = "test_topic";
                var exchangeType = "topic"; //direct
                var routingKey = "a.info";
                using (var connection = factory.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        // 设置交换器的类型
                        channel.ExchangeDeclare(exchangeName, exchangeType, durable: true);

                        // 声明一个队列，设置队列是否持久化，排他性，与自动删除
                        channel.QueueDeclare(qName1, true, false, false);
                        channel.QueueDeclare(qName2, true, false, false);
                        channel.QueueDeclare(qName3, true, false, false);

                        // 绑定消息队列，交换器，routingkey
                        channel.QueueBind(qName1, exchangeName, routingKey: "#.error");
                        channel.QueueBind(qName2, exchangeName, routingKey: "#.info");
                        channel.QueueBind(qName3, exchangeName, routingKey: "order.#");
                        var properties = channel.CreateBasicProperties();

                        // 队列持久化
                        properties.Persistent = true;
                        var body = Encoding.UTF8.GetBytes(textBox1.Text);
                        // 发送信息
                        channel.BasicPublish(exchangeName, routingKey, properties, body);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            try
            {
                var qName1 = "test_topic_queue1";
                var qName2 = "test_topic_queue2";
                var qName3 = "test_topic_queue3";
                var exchangeName = "test_topic";
                var exchangeType = "topic"; //direct
                var routingKey = "a.info";
                using (var connection = factory.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        // 设置交换器的类型
                        channel.ExchangeDeclare(exchangeName, exchangeType, durable: true);

                        // 声明一个队列，设置队列是否持久化，排他性，与自动删除
                        channel.QueueDeclare(qName1, true, false, false);
                        channel.QueueDeclare(qName2, true, false, false);
                        channel.QueueDeclare(qName3, true, false, false);

                        // 绑定消息队列，交换器，routingkey
                        channel.QueueBind(qName1, exchangeName, routingKey: "#.error");
                        channel.QueueBind(qName2, exchangeName, routingKey: "#.info");
                        channel.QueueBind(qName3, exchangeName, routingKey: "order.#");
                        var properties = channel.CreateBasicProperties();

                        // 队列持久化
                        properties.Persistent = true;
                        var body = Encoding.UTF8.GetBytes(textBox1.Text);
                        // 发送信息
                        channel.BasicPublish(exchangeName, routingKey, properties, body);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            try
            {
                var qName1 = "test_topic_queue1";
                var qName2 = "test_topic_queue2";
                var qName3 = "test_topic_queue3";
                var exchangeName = "test_topic";
                var exchangeType = "topic"; //direct
                var routingKey = "a.info";
                using (var connection = factory.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        // 设置交换器的类型
                        channel.ExchangeDeclare(exchangeName, exchangeType, durable: true);

                        // 声明一个队列，设置队列是否持久化，排他性，与自动删除
                        channel.QueueDeclare(qName1, true, false, false);
                        channel.QueueDeclare(qName2, true, false, false);
                        channel.QueueDeclare(qName3, true, false, false);

                        // 绑定消息队列，交换器，routingkey
                        channel.QueueBind(qName1, exchangeName, routingKey: "#.error");
                        channel.QueueBind(qName2, exchangeName, routingKey: "#.info");
                        channel.QueueBind(qName3, exchangeName, routingKey: "order.#");
                        var properties = channel.CreateBasicProperties();

                        // 队列持久化
                        properties.Persistent = true;
                        var body = Encoding.UTF8.GetBytes(textBox1.Text);
                        // 发送信息
                        channel.BasicPublish(exchangeName, routingKey, properties, body);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void textBox2_MouseClick(object sender, MouseEventArgs e)
        {
            textBox2.Clear();
        }

        private void textBox3_MouseClick(object sender, MouseEventArgs e)
        {
            textBox3.Clear();
        }
        /// <summary>
        /// 指定队列发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            string queueName = textBox2.Text;
            Thread thread = new Thread(new ParameterizedThreadStart(productSpelQueueMsg));
            thread.Start(queueName);
            (sender as Button).Enabled = false;
        }

        /// <summary>
        /// 给指定队列发送1000条消息
        /// </summary>
        /// <param name="queueName"></param>
        private void productSpelQueueMsg(object queueName)
        {
            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    QueueDeclareOk queue = channel.QueueDeclare(
                        queue: queueName.ToString(),
                        durable: true,
                        exclusive: false,
                        autoDelete: false,
                        arguments: null);
                    for (int i = 0; i < 10000; i++)
                    {
                        var body = Encoding.UTF8.GetBytes($"{textBox1.Text ?? "hello world"}:{i + 1}");
                        channel.BasicPublish(
                        exchange: string.Empty,
                        routingKey: queueName.ToString(),
                        basicProperties: null,
                        body: body);
                    }
                }
            };
        }

        /// <summary>
        /// 接收指定队列的消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button8_Click(object sender, EventArgs e)
        {
            Thread newThread = new Thread(new ParameterizedThreadStart(consumeSplQueueMsg));
            newThread.Priority = ThreadPriority.BelowNormal;
            newThread.Start(textBox3.Text);
            (sender as Button).Enabled = false;
        }

        /// <summary>
        /// 消费指定队列的消息
        /// </summary>
        /// <param name="queueName"></param>
        private void consumeSplQueueMsg(object queueName)
        {

            string queue = queueName.ToString();

            // 您的后台任务代码  
            IConnection connection = factory.CreateConnection();//创建连接对象
            IModel channel = connection.CreateModel();//创建连接会话对象

            // 声明队列
            channel.QueueDeclare(queue: queue,//消息队列名称
              durable: true,//是否持久化,true持久化,队列会保存磁盘,服务器重启时可以保证不丢失相关信息。
              exclusive: false,//是否排他,true排他的,如果一个队列声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除.
              autoDelete: false,//是否自动删除。true是自动删除。自动删除的前提是：致少有一个消费者连接到这个队列，之后所有与这个队列连接的消费者都断开时,才会自动删除.
              arguments: null //设置队列的一些其它参数
            );

            // 定义消费者
            var consumer = new EventingBasicConsumer(channel);

            // 接收事件 public delegate void EventHandler<TEventArgs>(object? sender, TEventArgs e);
            consumer.Received += (model, ea) =>
            {
                try
                {
                    // 接收到的消息
                    byte[] message = ea.Body.ToArray();

                    if (textBox1.InvokeRequired)
                    {
                        textBox1.Invoke(new MethodInvoker(delegate
                        {
                            // 在这里执行对textBox1的操作  
                            string str = Encoding.UTF8.GetString(message);
                            textBox1.Text = str;
                        }));
                    }
                }
                catch (ObjectDisposedException)
                {
                    // 处理对象已被释放的情况  
                    MessageBox.Show($"{ea.DeliveryTag},{ea.ConsumerTag}");
                }
                finally
                {
                    // 返回消息确认
                    channel.BasicAck(ea.DeliveryTag, true);
                }
            };

            // 开启监听
            while (true) // 不需要这个 while true
            {
                channel.BasicConsume(queue, false, consumer);
            }
        }
        /// <summary>
        /// 异步接收消息队列的消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button9_Click(object sender, EventArgs e)
        {
            await ConsumeSplQueueMsg2(textBox3.Text);
            (sender as Button).Enabled = false;
        }

        /// <summary>
        /// 异步消费消息
        /// </summary>
        /// <param name="queueName"></param>
        /// <returns></returns>
        private async Task<Task> ConsumeSplQueueMsg2(object queueName)
        {
            string queue = queueName.ToString();

            return Task.Run(() =>
            {
                // 您的后台任务代码  
                IConnection connection = factory.CreateConnection();//创建连接对象
                IModel channel = connection.CreateModel();//创建连接会话对象

                // 声明队列
                channel.QueueDeclare(queue: queue,//消息队列名称
                  durable: true,//是否持久化,true持久化,队列会保存磁盘,服务器重启时可以保证不丢失相关信息。
                  exclusive: false,//是否排他,true排他的,如果一个队列声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除.
                  autoDelete: false,//是否自动删除。true是自动删除。自动删除的前提是：致少有一个消费者连接到这个队列，之后所有与这个队列连接的消费者都断开时,才会自动删除.
                  arguments: null //设置队列的一些其它参数
                );

                // 定义消费者
                var consumer = new EventingBasicConsumer(channel);

                // 接收事件 public delegate void EventHandler<TEventArgs>(object? sender, TEventArgs e);
                consumer.Received += (model, ea) =>
                {
                    try
                    {
                        // 接收到的消息
                        byte[] message = ea.Body.ToArray();

                        if (textBox1.InvokeRequired)
                        {
                            textBox1.Invoke(new MethodInvoker(delegate
                            {
                                // 在这里执行对textBox1的操作  
                                string str = Encoding.UTF8.GetString(message);
                                textBox1.Text = str;
                            }));
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // 处理对象已被释放的情况  
                        MessageBox.Show($"{ea.DeliveryTag},{ea.ConsumerTag}");
                    }
                    finally
                    {
                        // 返回消息确认
                        channel.BasicAck(ea.DeliveryTag, true);
                    }
                };

                // 开启监听
                while (true) // 后面的案例证明，不需要这个while true
                {
                    channel.BasicConsume(queue, false, consumer);
                }
            });
        }

        /// <summary>
        /// 异步接收消息队列消息，并且将按钮失效掉
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button10_Click(object sender, EventArgs e)
        {
            await ConsumeSplQueueMsg3(textBox3.Text);
            (sender as Button).Enabled = false;
        }

        private async Task<Task> ConsumeSplQueueMsg3(object queueName)
        {
            string queue = queueName.ToString();

            return Task.Run(() =>
            {
                // 您的后台任务代码  
                IConnection connection = factory.CreateConnection();//创建连接对象
                IModel channel = connection.CreateModel();//创建连接会话对象

                // 声明队列
                channel.QueueDeclare(queue: queue,//消息队列名称
                  durable: true,//是否持久化,true持久化,队列会保存磁盘,服务器重启时可以保证不丢失相关信息。
                  exclusive: false,//是否排他,true排他的,如果一个队列声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除.
                  autoDelete: false,//是否自动删除。true是自动删除。自动删除的前提是：致少有一个消费者连接到这个队列，之后所有与这个队列连接的消费者都断开时,才会自动删除.
                  arguments: null //设置队列的一些其它参数
                );

                // 定义消费者
                var consumer = new EventingBasicConsumer(channel);

                // 接收事件 public delegate void EventHandler<TEventArgs>(object? sender, TEventArgs e);
                consumer.Received += (model, ea) =>
                {
                    try
                    {
                        // 接收到的消息
                        byte[] message = ea.Body.ToArray();

                        if (textBox1.InvokeRequired)
                        {
                            textBox1.Invoke(new MethodInvoker(delegate
                            {
                                // 在这里执行对textBox1的操作  
                                string str = Encoding.UTF8.GetString(message);
                                textBox1.Text = str;
                            }));
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // 处理对象已被释放的情况  
                        MessageBox.Show($"{ea.DeliveryTag},{ea.ConsumerTag}");
                    }
                    finally
                    {
                        // 返回消息确认
                        channel.BasicAck(ea.DeliveryTag, true);
                    }
                };
                // 开启监听
                channel.BasicConsume(queue, false, consumer);
            });
        }
        /// <summary>
        /// 发送scada消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button11_Click(object sender, EventArgs e)
        {

            ConnectionFactory factory2 = new ConnectionFactory 
            { 
                HostName = "10.16.152.203", 
                Port = 5672 ,
                UserName="test",
                Password= "Un9Q4Jxw^D8f" 
            };

            string queueName = "prod_dzgs_equip_scada_msg";
            using (var connection = factory2.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    QueueDeclareOk queue = channel.QueueDeclare(
                        queue: queueName.ToString(),
                        durable: true,
                        exclusive: false,
                        autoDelete: false,
                        arguments: null);
                    for (int i = 0; i < 100; i++)
                    {
                        Dictionary<string, string> map = new Dictionary<string, string>();
                        map.Add("温度", "15");
                        map.Add("湿度", "5.5");
                        map.Add("时间", "2023-12-01 12:45:45");
                        string json = JsonConvert.SerializeObject(map);

                        ScadaData1 d1 = new ScadaData1
                        {
                            labEquipmentNumber = "A2201020004220081",
                            data = json
                        };

                        string data = JsonConvert.SerializeObject(d1 );
                        

                        var body = Encoding.UTF8.GetBytes(data);
                        channel.BasicPublish(
                        exchange: string.Empty,
                        routingKey: queueName.ToString(),
                        basicProperties: null,
                        body: body);
                    }
                }
            };
        }
    }

    public class ScadaData1
    {
        public string labEquipmentNumber { get; set; }
        public string data { get; set; }


    }
}
